/**
 * OSAmI: Open Source Ambient Intelligence
 * Copyright (C) 2010 UJF.
 * Contact: osami-general@osami-commons.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 */

package org.osami.gateway.mediator.storage;

import java.io.IOException;
import java.util.Date;

import javax.jms.JMSException;
import javax.jms.ObjectMessage;
import javax.naming.NamingException;

import org.osami.commons.encryption.iface.SymmetricEncryptionService;
import org.osami.commons.encryption.iface.exception.EncryptionException;
import org.osami.gateway.alarm.IAlarm;
import org.osami.gateway.alarm.Severity;
import org.osami.gateway.mediator.storage.encryption.Constants;
import org.osami.gateway.mediator.storage.encryption.EncryptionHelper;
import org.osami.gateway.storage.IAlarmStorage;
import org.osgi.service.log.LogService;

import fr.liglab.adele.cilia.CiliaException;
import fr.liglab.adele.cilia.Data;

public class MediatorAlarmStorage {


	private LogService logger;
	private SymmetricEncryptionService encryptionService;
	private IAlarmStorage storage;

	public MediatorAlarmStorage(){

		try {

			EncryptionHelper.init();

		} catch (IOException e) {
			logger.log(LogService.LOG_ERROR,"Could not load key for encryption service: "+e.getMessage(),e);
		} catch (NamingException e) {
			logger.log(LogService.LOG_ERROR,"Could not obtain information from JNDI: "+e.getMessage(),e);
		} catch (EncryptionException e) {
			logger.log(LogService.LOG_ERROR,"Could not load key for encryption service: "+e.getMessage(),e);
		}
	}

	/**
	 * Store the Alarm triggered by drools.
	 * @throws CiliaException if the data does not contain an IAlarm
	 */
	public Data process(Data data) throws CiliaException {
		IAlarm alarm;

		try {
			if (data.getType() != null && data.getType().equals(IAlarm.class.getName())) {
				alarm = (IAlarm) data.getContent();
			} else {
				alarm = new IAlarmImpl(data);
			}
		} catch (Exception e) {
			logger.log(LogService.LOG_WARNING, "Cannot get The IAlarm from the data ! bad data : " + data.toString(), e);
			throw new CiliaException("Cannot get The IAlarm from the data ! bad data: " + e.getMessage());
		}
		//Store the alarm by using the storage service
		try {
			storage.store(alarm);
		} catch (Exception e) {
			logger.log(LogService.LOG_ERROR, "An Exception occured while storing the data: " + e.getMessage(), e);
		}

		/*
		 * The following is commented since we cannot send message to the JMS Queue in 
		 * the standard way (classloader problem)
		 * TODO: ask Guillaume about the code needed for changing classloaders
		 */
		
//		try {
//
//			
//			ObjectMessage objectMessage;
//			//Encrypt alarm object
//			objectMessage = EncryptionHelper.encryptAlarm(alarm,encryptionService);
//			//Send data to the backoffice via JMS
//			EncryptionHelper.sendObjectMessage(objectMessage,Constants.JMS_QUEUE);
//
//		} catch (JMSException e) {
//			logger.log(LogService.LOG_ERROR,"Could not access the JMS Queue: "+e.getMessage(),e);
//		} catch (IOException e) {
//			logger.log(LogService.LOG_ERROR,"Could not convert the alarm to byte array: "+e.getMessage(),e);
//		} catch (NamingException e) {
//			logger.log(LogService.LOG_ERROR,"Could not access the JMS Queue: "+e.getMessage(),e);
//		} catch (EncryptionException e) {
//			logger.log(LogService.LOG_ERROR,"Could not use the encryption service: "+e.getMessage(),e);
//		}


		return data;
	}


	/**
	 * IAlarm implementation thanks to a Data object (map).
	 */
	private class IAlarmImpl implements IAlarm {

		private static final String MESSAGE_KEY = "description";

		private static final String DATE_KEY = "timestamp";

		private static final String IDENTIFIER_KEY = "identifier";

		private final String message;

		private final Date timestamp;

		private final String identifier;

		/**
		 * Parse the data.
		 * @param data
		 * @throws IllegalArgumentException if the data does not correspond to
		 *         an IAlarm.
		 */
		public IAlarmImpl(Data data) throws IllegalArgumentException {
			try {
				message = (String) data.getProperty(MESSAGE_KEY);
				timestamp = new Date((Long) data.getProperty(DATE_KEY));
				identifier = (String) data.getProperty(IDENTIFIER_KEY);
			} catch (ClassCastException ce) {
				throw new IllegalArgumentException(ce);
			} catch (NullPointerException ne) {
				throw new IllegalArgumentException(ne);
			}

			if (message == null || timestamp == null || identifier == null) {
				throw new IllegalArgumentException("The alarm property: " + DATE_KEY + ", " + IDENTIFIER_KEY + ", " + MESSAGE_KEY + " must be set");
			}
		}

		public Severity getSeverity() {
			// TODO How I get the severity ?
			return Severity.WARNING;
		}

		public String getMessage() {
			return message;
		}

		public String getIdentifier() {
			return identifier;
		}

		public Date getGenerationDate() {
			return timestamp;
		}

		public void disengage() {
			// TODO Should I do something ?
					throw new UnsupportedOperationException();
		}
	}

}
